package com.woniu.config;

import com.woniu.hander.*;
import com.woniu.service.SecurityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * 实现指定用户名和密码,继承WebSecurityConfigurerAdapter,重写方法
 */
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private SecurityService securityService;

    @Autowired
    private LoginSuccessHandler loginSuccessHandler;

    @Autowired
    private JWTFilter jwtFilter;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //实现指定用户名和密码的功能,
        //第一种方式,用户名,密码以内存参数的方式实现
        //BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        //String password = passwordEncoder.encode("666");
        //auth.inMemoryAuthentication().withUser("tom").password(password).roles("admin");

        //第二种方式,写service类SecurityService实现继承UserDetailsService
        auth.userDetailsService(securityService);
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    //自定义登录页面
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin() //告诉security 用自定义登录页面
                //.loginPage("/login.html")
                //.loginProcessingUrl("/dologin") //前后端分离是没有这两个页面的
                //.successHandler(new LoginSuccessHandler())  //登录成功返回相应提示代码,原先是new出来，现在要放在spring容器中
                .successHandler(loginSuccessHandler)
                .failureHandler(new LoginFailedHandler())
                .failureHandler(new LoginDisable())  //登录失败返回响应提示代码
                .permitAll(); //放行 login.html 和dologin请求

        http.exceptionHandling() //未登录先登录
                .authenticationEntryPoint(new MyAuthenticationEntryPoint()) //未登录先登录
                .accessDeniedHandler(new MyAccessDeniedHandler());  //登录无权限

        http.logout().logoutSuccessHandler(new LoginoutHandler());//退出


        http.authorizeRequests()

                //一个url角色只能邦一个权限
                .antMatchers("/dalete").hasAuthority("admin")//给指定的url访问权限访问哪个路径页面后面给什么（admin）权限
                //一个url角色可以绑多个权限
                .antMatchers("/dalete").hasAnyAuthority("admin","user")
                //配置免登录注册的url
                .antMatchers("/sendCode","/codeLogin","/app/**","/uploadimg","/imgUpload").permitAll()  //放行路径

                .anyRequest().authenticated(); //所有的请求都会被拦截

        //系统禁用session，只用jwt
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        http.addFilterAfter(jwtFilter, UsernamePasswordAuthenticationFilter.class);

        //关闭跨站脚本攻击
        http.csrf().disable();

        //允许跨域请求
        http.cors();
    }
}
